"======================================================================
"
" init-keymaps.vim - 按键设置，按你喜欢更改
"
"   - 快速移动
"   - 标签切换
"   - 窗口切换
"   - 终端支持
"   - 编译运行
"   - 符号搜索
"
" Created by skywind on 2018/05/30
" Last Modified: 2018/05/30 17:59:31
"
"======================================================================
" vim: set ts=4 sw=4 tw=78 noet :


"----------------------------------------------------------------------
" INSERT 模式下使用 EMACS 键位
"----------------------------------------------------------------------
" inoremap <c-a> <home>
" inoremap <c-e> <end>
" inoremap <c-d> <del>
" inoremap <c-_> <c-k>


"----------------------------------------------------------------------
" 设置 CTRL+HJKL 移动光标（INSERT 模式偶尔需要移动的方便些）
" 使用 SecureCRT/XShell 等终端软件需设置：Backspace sends delete
" 详见：http://www.skywind.me/blog/archives/2021
"----------------------------------------------------------------------
" noremap <C-h> <left>
" noremap <C-j> <down>
" noremap <C-k> <up>
" noremap <C-l> <right>
inoremap <C-h> <left>
inoremap <C-j> <down>
inoremap <C-k> <up>
inoremap <C-l> <right>


"----------------------------------------------------------------------
" 命令模式的快速移动
"----------------------------------------------------------------------
cnoremap <c-h> <left>
cnoremap <c-j> <down>
cnoremap <c-k> <up>
cnoremap <c-l> <right>
" cnoremap <c-a> <home>
" cnoremap <c-e> <end>
" cnoremap <c-f> <c-d>
" cnoremap <c-b> <left>
" cnoremap <c-d> <del>
" cnoremap <c-_> <c-k>


"----------------------------------------------------------------------
" <leader>+数字键 切换tab
"----------------------------------------------------------------------
" noremap <silent><leader>1 1gt<cr>
" noremap <silent><leader>2 2gt<cr>
" noremap <silent><leader>3 3gt<cr>
" noremap <silent><leader>4 4gt<cr>
" noremap <silent><leader>5 5gt<cr>
" noremap <silent><leader>6 6gt<cr>
" noremap <silent><leader>7 7gt<cr>
" noremap <silent><leader>8 8gt<cr>
" noremap <silent><leader>9 9gt<cr>
" noremap <silent><leader>0 10gt<cr>


"----------------------------------------------------------------------
" ALT+N 切换 tab
"----------------------------------------------------------------------
" noremap <silent><m-1> :tabn 1<cr>
" noremap <silent><m-2> :tabn 2<cr>
" noremap <silent><m-3> :tabn 3<cr>
" noremap <silent><m-4> :tabn 4<cr>
" noremap <silent><m-5> :tabn 5<cr>
" noremap <silent><m-6> :tabn 6<cr>
" noremap <silent><m-7> :tabn 7<cr>
" noremap <silent><m-8> :tabn 8<cr>
" noremap <silent><m-9> :tabn 9<cr>
" noremap <silent><m-0> :tabn 10<cr>
" inoremap <silent><m-1> <ESC>:tabn 1<cr>
" inoremap <silent><m-2> <ESC>:tabn 2<cr>
" inoremap <silent><m-3> <ESC>:tabn 3<cr>
" inoremap <silent><m-4> <ESC>:tabn 4<cr>
" inoremap <silent><m-5> <ESC>:tabn 5<cr>
" inoremap <silent><m-6> <ESC>:tabn 6<cr>
" inoremap <silent><m-7> <ESC>:tabn 7<cr>
" inoremap <silent><m-8> <ESC>:tabn 8<cr>
" inoremap <silent><m-9> <ESC>:tabn 9<cr>
" inoremap <silent><m-0> <ESC>:tabn 10<cr>


" MacVim 允许 CMD+数字键快速切换标签
" if has("gui_macvim")
" 	set macmeta
" 	noremap <silent><d-1> :tabn 1<cr>
" 	noremap <silent><d-2> :tabn 2<cr>
" 	noremap <silent><d-3> :tabn 3<cr>
" 	noremap <silent><d-4> :tabn 4<cr>
" 	noremap <silent><d-5> :tabn 5<cr>
" 	noremap <silent><d-6> :tabn 6<cr>
" 	noremap <silent><d-7> :tabn 7<cr>
" 	noremap <silent><d-8> :tabn 8<cr>
" 	noremap <silent><d-9> :tabn 9<cr>
" 	noremap <silent><d-0> :tabn 10<cr>
" 	inoremap <silent><d-1> <ESC>:tabn 1<cr>
" 	inoremap <silent><d-2> <ESC>:tabn 2<cr>
" 	inoremap <silent><d-3> <ESC>:tabn 3<cr>
" 	inoremap <silent><d-4> <ESC>:tabn 4<cr>
" 	inoremap <silent><d-5> <ESC>:tabn 5<cr>
" 	inoremap <silent><d-6> <ESC>:tabn 6<cr>
" 	inoremap <silent><d-7> <ESC>:tabn 7<cr>
" 	inoremap <silent><d-8> <ESC>:tabn 8<cr>
" 	inoremap <silent><d-9> <ESC>:tabn 9<cr>
" 	inoremap <silent><d-0> <ESC>:tabn 10<cr>
" endif



"----------------------------------------------------------------------
" 缓存：插件 unimpaired 中定义了 [b, ]b 来切换缓存
"----------------------------------------------------------------------
" noremap <silent> <leader>bn :bn<cr>
" noremap <silent> <leader>bp :bp<cr>


"----------------------------------------------------------------------
" TAB：创建，关闭，上一个，下一个，左移，右移
" 其实还可以用原生的 CTRL+PageUp, CTRL+PageDown 来切换标签
"----------------------------------------------------------------------

nnoremap <silent> <leader>tn :tabnew<cr>
nnoremap <silent> <leader>tw :tabclose<cr>
nnoremap <silent> <leader>th :tabp<cr>
nnoremap <silent> <leader>tl :tabn<cr>


" 左移 tab
function! Tab_MoveLeft()
	let l:tabnr = tabpagenr() - 2
	if l:tabnr >= 0
		exec 'tabmove '.l:tabnr
	endif
endfunc

" 右移 tab
function! Tab_MoveRight()
	let l:tabnr = tabpagenr() + 1
	if l:tabnr <= tabpagenr('$')
		exec 'tabmove '.l:tabnr
	endif
endfunc

nnoremap <silent> <leader>tk :call Tab_MoveLeft()<cr>
nnoremap <silent> <leader>tj :call Tab_MoveRight()<cr>
" noremap <silent><m-left> :call Tab_MoveLeft()<cr>
" noremap <silent><m-right> :call Tab_MoveRight()<cr>


"----------------------------------------------------------------------
" ALT 键移动增强
"----------------------------------------------------------------------

" ALT+h/l 快速左右按单词移动（正常模式+插入模式）
nnoremap <m-h> b
nnoremap <m-l> w
inoremap <m-h> <c-left>
inoremap <m-l> <c-right>

" ALT+j/k 逻辑跳转下一行/上一行（按 wrap 逻辑换行进行跳转） 
nnoremap <m-j> gj
nnoremap <m-k> gk
inoremap <m-j> <c-\><c-o>gj
inoremap <m-k> <c-\><c-o>gk

" 命令模式下的相同快捷
cnoremap <m-h> <c-left>
cnoremap <m-l> <c-right>

" ALT+y 删除到行末
" noremap <m-y> d$
" inoremap <m-y> <c-\><c-o>d$
nnoremap <m-9> d$
inoremap <m-9> <c-\><c-o>d$
nnoremap <m-2> d^
inoremap <m-2> <c-\><c-o>d^
nnoremap <m-0> $
inoremap <m-0> <c-\><c-o>$
nnoremap <m-1> ^
inoremap <m-1> <c-\><c-o>^

nnoremap <m-z> u
nnoremap <m-Z> <c-r>
nnoremap <m-v> :reg<cr>
inoremap <m-z> <c-o>u
inoremap <m-Z> <c-o><c-r>
nnoremap <m-v> <c-o>:reg<cr>


"----------------------------------------------------------------------
" 窗口切换：ALT+SHIFT+hjkl
" 传统的 CTRL+hjkl 移动窗口不适用于 vim 8.1 的终端模式，CTRL+hjkl 在
" bash/zsh 及带文本界面的程序中都是重要键位需要保留，不能 tnoremap 的
"----------------------------------------------------------------------
nnoremap <m-H> <c-w>h
nnoremap <m-L> <c-w>l
nnoremap <m-J> <c-w>j
nnoremap <m-K> <c-w>k
inoremap <m-H> <esc><c-w>h
inoremap <m-L> <esc><c-w>l
inoremap <m-J> <esc><c-w>j
inoremap <m-K> <esc><c-w>k

if has('terminal') && exists(':terminal') == 2 && has('patch-8.1.1')
	" vim 8.1 支持 termwinkey ，不需要把 terminal 切换成 normal 模式
	" 设置 termwinkey 为 CTRL 加减号（GVIM），有些终端下是 CTRL+?
	" 后面四个键位是搭配 termwinkey 的，如果 termwinkey 更改，也要改
	set termwinkey=<c-_>
	tnoremap <m-H> <c-_>h
	tnoremap <m-L> <c-_>l
	tnoremap <m-J> <c-_>j
	tnoremap <m-K> <c-_>k
	tnoremap <m-q> <c-\><c-n>
elseif has('nvim')
	" neovim 没有 termwinkey 支持，必须把 terminal 切换回 normal 模式
	tnoremap <m-H> <c-\><c-n><c-w>h
	tnoremap <m-L> <c-\><c-n><c-w>l
	tnoremap <m-J> <c-\><c-n><c-w>j
	tnoremap <m-K> <c-\><c-n><c-w>k
	tnoremap <m-q> <c-\><c-n>
endif



" "----------------------------------------------------------------------
" " 编译运行 C/C++ 项目
" " 详细见：http://www.skywind.me/blog/archives/2084
" "----------------------------------------------------------------------

" " 自动打开 quickfix window ，高度为 6
" let g:asyncrun_open = 6

" " 任务结束时候响铃提醒
" let g:asyncrun_bell = 1

" " 设置 F10 打开/关闭 Quickfix 窗口
" nnoremap <F10> :call asyncrun#quickfix_toggle(6)<cr>

" " F9 编译 C/C++ 文件
" nnoremap <silent> <F9> :AsyncRun gcc -Wall -O2 "$(VIM_FILEPATH)" -o "$(VIM_FILEDIR)/$(VIM_FILENOEXT)" <cr>

" " F5 运行文件
" nnoremap <silent> <F5> :call ExecuteFile()<cr>

" " F7 编译项目
" nnoremap <silent> <F7> :AsyncRun -cwd=<root> make <cr>

" " F8 运行项目
" nnoremap <silent> <F8> :AsyncRun -cwd=<root> -raw make run <cr>

" " F6 测试项目
" nnoremap <silent> <F6> :AsyncRun -cwd=<root> -raw make test <cr>

" " 更新 cmake
" nnoremap <silent> <F4> :AsyncRun -cwd=<root> cmake . <cr>

" " Windows 下支持直接打开新 cmd 窗口运行
" if has('win32') || has('win64')
" 	nnoremap <silent> <F8> :AsyncRun -cwd=<root> -mode=4 make run <cr>
" endif


" "----------------------------------------------------------------------
" " F5 运行当前文件：根据文件类型判断方法，并且输出到 quickfix 窗口
" "----------------------------------------------------------------------
" function! ExecuteFile()
" 	let cmd = ''
" 	if index(['c', 'cpp', 'rs', 'go'], &ft) >= 0
" 		" native 语言，把当前文件名去掉扩展名后作为可执行运行
" 		" 写全路径名是因为后面 -cwd=? 会改变运行时的当前路径，所以写全路径
" 		" 加双引号是为了避免路径中包含空格
" 		let cmd = '"$(VIM_FILEDIR)/$(VIM_FILENOEXT)"'
" 	elseif &ft == 'python'
" 		let $PYTHONUNBUFFERED=1 " 关闭 python 缓存，实时看到输出
" 		let cmd = 'python "$(VIM_FILEPATH)"'
" 	elseif &ft == 'javascript'
" 		let cmd = 'node "$(VIM_FILEPATH)"'
" 	elseif &ft == 'perl'
" 		let cmd = 'perl "$(VIM_FILEPATH)"'
" 	elseif &ft == 'ruby'
" 		let cmd = 'ruby "$(VIM_FILEPATH)"'
" 	elseif &ft == 'php'
" 		let cmd = 'php "$(VIM_FILEPATH)"'
" 	elseif &ft == 'lua'
" 		let cmd = 'lua "$(VIM_FILEPATH)"'
" 	elseif &ft == 'zsh'
" 		let cmd = 'zsh "$(VIM_FILEPATH)"'
" 	elseif &ft == 'ps1'
" 		let cmd = 'powershell -file "$(VIM_FILEPATH)"'
" 	elseif &ft == 'vbs'
" 		let cmd = 'cscript -nologo "$(VIM_FILEPATH)"'
" 	elseif &ft == 'sh'
" 		let cmd = 'bash "$(VIM_FILEPATH)"'
" 	else
" 		return
" 	endif
" 	" Windows 下打开新的窗口 (-mode=4) 运行程序，其他系统在 quickfix 运行
" 	" -raw: 输出内容直接显示到 quickfix window 不匹配 errorformat
" 	" -save=2: 保存所有改动过的文件
" 	" -cwd=$(VIM_FILEDIR): 运行初始化目录为文件所在目录
" 	if has('win32') || has('win64')
" 		exec 'AsyncRun -cwd=$(VIM_FILEDIR) -raw -save=2 -mode=4 '. cmd
" 	else
" 		exec 'AsyncRun -cwd=$(VIM_FILEDIR) -raw -save=2 -mode=0 '. cmd
" 	endif
" endfunc



" "----------------------------------------------------------------------
" " F2 在项目目录下 Grep 光标下单词，默认 C/C++/Py/Js ，扩展名自己扩充
" " 支持 rg/grep/findstr ，其他类型可以自己扩充
" " 不是在当前目录 grep，而是会去到当前文件所属的项目目录 project root
" " 下面进行 grep，这样能方便的对相关项目进行搜索
" "----------------------------------------------------------------------
" if executable('rg')
" 	noremap <silent><F2> :AsyncRun! -cwd=<root> rg -n --no-heading 
" 				\ --color never -g *.h -g *.c* -g *.py -g *.js -g *.vim 
" 				\ <C-R><C-W> "<root>" <cr>
" elseif has('win32') || has('win64')
" 	noremap <silent><F2> :AsyncRun! -cwd=<root> findstr /n /s /C:"<C-R><C-W>" 
" 				\ "\%CD\%\*.h" "\%CD\%\*.c*" "\%CD\%\*.py" "\%CD\%\*.js"
" 				\ "\%CD\%\*.vim"
" 				\ <cr>
" else
" 	noremap <silent><F2> :AsyncRun! -cwd=<root> grep -n -s -R <C-R><C-W> 
" 				\ --include='*.h' --include='*.c*' --include='*.py' 
" 				\ --include='*.js' --include='*.vim'
" 				\ '<root>' <cr>
" endif


